<script lang="ts" setup name="proForm">
import { Message, Notification } from "@arco-design/web-vue";
import type { FieldRule } from "@arco-design/web-vue";
import { ref, reactive, shallowRef, customRef } from "vue";

export interface Mapping {
  label: string;
  prop: string;
  type: "input" | "select" | "radio" | "checkbox" | "date-range";

  options?: Option[] | string[];
  required?: boolean;
  rules?: Record<string, FieldRule | FieldRule[]>;

  col?: number;
  width?: string;
}

export interface Option {
  label: string;
  value: any;
}

export interface Props {
  modelValue: any;
  mapping: Mapping[];
  defaultCol?: number;
}
// 组件渲染映射表
enum FormItemMap {
  "input" = "a-input",
  "select" = "a-select",
  "radio" = "a-radio-group",
  "checkbox" = "a-checkbox-group",
  "date-range" = "a-range-picker",
}

const props = defineProps<Props>();

const { modelValue, mapping, defaultCol } = reactive<Props>(props);

const emit = defineEmits(["update:modelValue", "submit"]);

const formRef = ref();

const reset = async () => {
  // bug :重置不会触发校验
  await formRef.value?.resetFields();
  return true;
  // handleClick();
};

const handleChange = async () => {
  const errors = await formRef.value?.validate();
  if (errors) return Message.warning("未填写完整");
  emit("submit");
};

const verify = async () => {
  const errors = await formRef.value?.validate();
  if (errors) Message.warning("未填写完整");
  return !errors;
};

defineExpose({ verify, reset });
</script>

<template>
  <a-form ref="formRef" :model="modelValue" auto-label-width>
    <a-row :gutter="[30, 10]" class="w-full">
      <a-col
        :span="item.col || defaultCol || 24"
        v-for="(item, index) in mapping"
        :key="'pro_form_item_' + index"
      >
        <a-form-item
          show-colon
          :field="item.prop"
          :label="item.label"
          :rules="
            item.rules || [
              { required: item.required, message: item.label + '不能为空' },
            ]
          "
        >
          <!-- 常规表单项 -->
          <template v-if="!item.type.includes('date')">
            <component
              :is="FormItemMap[item.type]"
              v-model="modelValue[item.prop]"
              @change="emit('submit')"
              :placeholder="`请${
                ['input'].includes(item.type) ? '输入' : '选择'
              }${item.label}`"
              :style="{ width: item.width }"
            >
              <!-- 下拉选择项 -->
              <template v-if="item.type === 'select'">
                <a-option
                  :value="option.value ?? option"
                  v-for="(option, i) in item.options"
                  :key="i"
                >
                  {{ option.label ?? option }}
                </a-option>
              </template>

              <!-- 单选项 -->
              <template v-if="item.type === 'radio'">
                <a-radio
                  :value="option.value ?? option"
                  v-for="(option, i) in item.options"
                  :key="i"
                >
                  {{ option.label ?? option }}
                </a-radio>
              </template>

              <!-- 复选框 -->
              <template v-if="item.type === 'checkbox'">
                <a-checkbox
                  :value="option.value ?? option"
                  v-for="(option, i) in item.options"
                  :key="i"
                >
                  {{ option.label ?? option }}
                </a-checkbox>
              </template></component
            >
          </template>

          <!-- 日期选择 -->
          <template v-else>
            <a-range-picker
              @change="emit('submit')"
              v-model="modelValue[item.prop]"
              :placeholder="['请选择开始时间', '请选择结束时间']"
              style="width: 360px"
              show-time
              :time-picker-props="{ defaultValue: ['00:00:00', '00:00:00'] }"
              format="YYYY-MM-DD HH:mm:ss"
            />
          </template>
        </a-form-item>
      </a-col>
      <a-col :span="6" class="flex-x-end">
        <a-space size="large">
          <slot> </slot>
        </a-space>
      </a-col>
    </a-row>
  </a-form>
</template>

<style lang="less" scoped></style>
